#pragma once
#include <iostream>
#include <unordered_map>
#include <regex>
#include <functional>
#include <cxxabi.h>


/**
 * Json类的使用方式
 * 1.有参构造函数构造
 * 2.调用void processingStart()函数处理传入的Json字符串
 * 3.
 */
namespace JsonTool {





    /**
         * 获取值类型
         * @tparam ValueType
         * @param value
         * @return
         * ===============================================================================
         */
    template<typename ValueType>
    std::string  getVauleType(ValueType value){

        int status = 0;
        const char* mangled = typeid(value).name();

        char* real_name  = abi::__cxa_demangle(mangled, nullptr, nullptr, &status);

        std::string result = (status == 0) ? real_name : mangled;

        free(real_name);
        return result;

    }


    /**
     * 数值格式字符串=====================================================================
     */
    class ValueTypeStr{

    private:

        static std::string intValueType;

        static std::string floatValueType;

        static std::string boolValueType;

        static std::string stringValueType;

    private:
        /***
         * 初始化value的数据类型，增加各个编译器的兼容性
         */
        static void initializationValueType(){
            int intValue;
            JsonTool::ValueTypeStr::intValueType = JsonTool::getVauleType(intValue);

            float floatValue;
            JsonTool::ValueTypeStr::floatValueType = JsonTool::getVauleType(floatValue);

            bool boolValue;
            JsonTool::ValueTypeStr::boolValueType = JsonTool::getVauleType(boolValue);

            std::string stringValue;
            JsonTool::ValueTypeStr::stringValueType = JsonTool::getVauleType(stringValue);
        }


    public:

        ValueTypeStr() = delete;

        ~ValueTypeStr() = default;

        friend class Json;
    };


    /**
     * re字符串=====================================================================
     */
    class RegexString{

    private:

        //去掉花括号
        static const std::string removeCurlyBracesReStr;

        //获取string
        static const std::string getStringValueReStr;

        //获取int
        static const std::string getIntValueReStr;

        //获取float
        static const std::string getFloatValueReStr;

        //获取bool
        static const std::string getBoolValueReStr;

    public:

        RegexString() = delete;

        ~RegexString() = default;

        friend class Json;
    };


    /**
     * 键值对
     * @tparam ValueType
     * ================================================================================
     */
    template<typename ValueType>
    class KeyValuePair{
    private:
        std::string key;
        ValueType value;
        std::string valueType;

        bool isNull = true;

    public:

        KeyValuePair() {

        }



        /**
         *
         * @param key
         * @param value
         */
        KeyValuePair(const std::string& key, const ValueType value){
            this->key = key;
            this->value = value;
            this->valueType = JsonTool::getVauleType(value);

            isNull = false;
        }






        /**
         * 重写拷贝函数
         * 变为深拷贝，防止从外部通过键值对访问键值对堆数据
         */
        KeyValuePair(const KeyValuePair& keyValuePair){
            this->value = keyValuePair.value;
            this->key = keyValuePair.key;
            this->valueType = keyValuePair.valueType;
            this->isNull = keyValuePair.isNull;
        }


        /**
         * 析构函数
         */
        ~KeyValuePair() = default;


        /**
         *
         * @return
         */
        ValueType getValue(){
            return this->value;
        }

        /**
         *
         * @return
         */
        std::string getKey(){
            return this->key;
        }


        /**
         * 是否为空
         * @return
         */
        bool empy(){
            return this->isNull;
        }
    };



    /**
     * 键值对堆数据
     */

    //需要重写拷贝函数、构造函数、赋值函数，防止类外访问堆数据
     class KeyValueHeapData{

     public:
         std::vector<KeyValuePair<int>> intHeapData;
         std::vector<KeyValuePair<float>> floatHeapData;
         std::vector<KeyValuePair<bool>> boolHeapData;
         std::vector<KeyValuePair<std::string>> stringHeapData;


     private:
         KeyValueHeapData(){}




         /**
          * 复制数据堆
          */

         /**
          * 析构函数，删除所有键值对堆数据
          */
         ~KeyValueHeapData(){

         }


     public:
         friend class Json;

     };







    /**
     * Json==================================================================
     */
    class Json{

    private:

        //键值对值格式
        std::unordered_map<std::string,std::string> keyValuePairsType;

        //键值对数据
        std::unordered_map<std::string,unsigned char*> keyValuePairs;

        //键值对堆数据
        KeyValueHeapData* keyValueHeapData = nullptr;

        std::string jsonStr;

        bool isStart = false;


    private:

        /**
         *
         * @param reStr
         * @param processingKeyValue std::string key,std::string value
         */
        void processingJsonStr(const std::string& reStr,std::function<void(std::string,std::string)> processingKeyValue){

            std::regex patten(reStr);
            std::sregex_iterator it(this->jsonStr.begin(), this->jsonStr.end(),patten);
            std::sregex_iterator end;

            for(;it!=end;it++){

                std::smatch smatchData = *it;

                //不存在键值对
                if(smatchData.size() < 3 ) continue;

                //处理key和value
                processingKeyValue(smatchData[1],smatchData[2]);
            }
        }

    public:

        /**
         *
         * @param jsonStr
         */
        Json(std::string jsonStr){

            this->jsonStr = jsonStr;
        }




        /**
         * 删除拷贝函数
         */
        Json(const Json&) = delete;

         /**
          * 删除赋值函数
          */
          Json& operator=(const Json) = delete;


        /**
         * 处理启动
         */
        void processingStart(){

            if (isStart) return ;

            isStart = true;

            //去除花括号
            std::regex patten(JsonTool::RegexString::removeCurlyBracesReStr);
            std::smatch smatchResult;

            if(!std::regex_match(this->jsonStr,smatchResult,patten)) return; //不符合格式
            this->jsonStr = smatchResult[1];

            //初始化数据类型
            JsonTool::ValueTypeStr::initializationValueType();

            //创建键值对数据堆
            this->keyValueHeapData = new KeyValueHeapData();

            //处理int类型
            std::function<void(std::string,std::string)> processingIntFunc = [&](std::string key,std::string value){
                int intValue = std::stoi(value);

                //注册类型
                this->keyValuePairsType[key] = JsonTool::ValueTypeStr::intValueType;

                //生成键值对
                KeyValuePair<int> keyValuePair(key,intValue);

                //注册键值对堆数据
                this->keyValueHeapData->intHeapData.push_back(keyValuePair);

                //this->keyValueHeapData->intHeapData.back()

                //序列化键值对对象地址，必须序列化数据堆的地址,否则该函数作用域消失，数据会为空
                unsigned char* keyValuePairChar = reinterpret_cast<unsigned char*>(&this->keyValueHeapData->intHeapData.back());

                //存储序列化数据
                this->keyValuePairs[key] = keyValuePairChar;

            };

            this->processingJsonStr(JsonTool::RegexString::getIntValueReStr,processingIntFunc);

            //处理float类型
            std::function<void(std::string,std::string)> processingFloatFunc = [&](std::string key,std::string value){

                float floatValue = std::stof(value);
                //注册类型
                this->keyValuePairsType[key] = JsonTool::ValueTypeStr::floatValueType;

                //生成键值对
                KeyValuePair<float> keyValuePair(key,floatValue);

                //注册键值对堆数据
                this->keyValueHeapData->floatHeapData.push_back(keyValuePair);

                //序列化键值对对象地址，必须序列化数据堆的地址,否则该函数作用域消失，数据会为空
                unsigned char* keyValuePairChar = reinterpret_cast<unsigned char*>(&this->keyValueHeapData->floatHeapData.back());

                //存储序列化数据
                this->keyValuePairs[key] = keyValuePairChar;


            };

            this->processingJsonStr(JsonTool::RegexString::getFloatValueReStr,processingFloatFunc);

            //处理bool类型
            std::function<void(std::string,std::string)> processingBoolFunc = [&](std::string key,std::string value){

                bool boolValue = value=="ture"? true: false;
                //注册类型
                this->keyValuePairsType[key] = JsonTool::ValueTypeStr::boolValueType;

                //生成键值对
                KeyValuePair<bool> keyValuePair(key,boolValue);

                //注册键值对堆数据
                this->keyValueHeapData->boolHeapData.push_back(keyValuePair);

                //序列化键值对对象地址，必须序列化数据堆的地址,否则该函数作用域消失，数据会为空
                unsigned char* keyValuePairChar = reinterpret_cast<unsigned char*>(&this->keyValueHeapData->boolHeapData.back());

                //存储序列化数据
                this->keyValuePairs[key] = keyValuePairChar;
            };

            this->processingJsonStr(JsonTool::RegexString::getBoolValueReStr,processingBoolFunc);


            //处理string类型
            std::function<void(std::string,std::string)> processingStringFunc = [&](std::string key,std::string value){


                //注册类型
                this->keyValuePairsType[key] = JsonTool::ValueTypeStr::stringValueType;

                //生成键值对
                KeyValuePair<std::string> keyValuePair(key,value);

                //注册键值对堆数据
                this->keyValueHeapData->stringHeapData.push_back(keyValuePair);

                //序列化键值对对象地址，必须序列化数据堆的地址,否则该函数作用域消失，数据会为空
                unsigned char* keyValuePairChar = reinterpret_cast<unsigned char*>(&this->keyValueHeapData->stringHeapData.back());

                //存储序列化数据
                this->keyValuePairs[key] = keyValuePairChar;
            };

            this->processingJsonStr(JsonTool::RegexString::getStringValueReStr,processingStringFunc);


        }



        /**
         * 获取键值对
         * @tparam ValueType
         * @param key
         * @return
         */
        template<typename ValueType>
        KeyValuePair<ValueType> getKeyValuePairByKey(std::string& key){

            //不存在该键值对
            if(this->keyValuePairs.count(key) < 1) return KeyValuePair<ValueType>();

            //转化为键值对类型
            KeyValuePair<ValueType>* keyValuePairPiont= reinterpret_cast<KeyValuePair<ValueType>*>(this->keyValuePairs[key]);


            return  *keyValuePairPiont;

        }



        /**
         * 析构函数
         */
         ~Json(){

             //清除键值对数据堆
             KeyValueHeapData* deleteHeapData = this->keyValueHeapData;
             this->keyValueHeapData = nullptr;
             delete deleteHeapData;
         }


    };




}


std::string JsonTool::ValueTypeStr::intValueType;
std::string JsonTool::ValueTypeStr::floatValueType;
std::string JsonTool::ValueTypeStr::boolValueType;
std::string JsonTool::ValueTypeStr::stringValueType;

const std::string JsonTool::RegexString::removeCurlyBracesReStr = R"(^\{(.*?)\}$)";
const std::string JsonTool::RegexString::getStringValueReStr = R"((\w+):\s*\"(.*?)\"\s*(?=,\w+:|$))";
const std::string JsonTool::RegexString::getIntValueReStr = R"((\w+):\s*(-?\d+)\s*(?=,\w+:|$))";
const std::string JsonTool::RegexString::getFloatValueReStr = R"((\w+):\s*(-?\d+\.\d+)\s*(?=,\w+:|$))";
const std::string JsonTool::RegexString::getBoolValueReStr = R"((\w+):\s*(true|false)\s*(?=,\w+:|$))";

